package oss.ngocminh.fw.forum;

import java.io.IOException;
import java.io.Reader;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.Header;
import org.apache.http.HttpResponse;

public class AdapterUtils {

	private static final Pattern ENCLOSING_TAG_PATTERN = Pattern.compile("\\s*<(\\w+)\\s+.+?>(.+)</\\1>\\s*", Pattern.DOTALL);
	private static final Pattern HTML_TAG_PATTERN = Pattern.compile("<(/)?\\s*(\\w+)[^>]*>");
	private static final Set<String> UNCLOSE_OK_TAGS;
	
	static {
		UNCLOSE_OK_TAGS = new HashSet<String>();
		UNCLOSE_OK_TAGS.add("br");
		UNCLOSE_OK_TAGS.add("p");
		UNCLOSE_OK_TAGS.add("img");
		UNCLOSE_OK_TAGS.add("h1");
		UNCLOSE_OK_TAGS.add("h2");
		UNCLOSE_OK_TAGS.add("h3");
		UNCLOSE_OK_TAGS.add("h4");
		UNCLOSE_OK_TAGS.add("h5");
		UNCLOSE_OK_TAGS.add("h6");
	}

	public static String md5(String str) {
		try {
			java.security.MessageDigest md = java.security.MessageDigest
					.getInstance("MD5");
			byte[] array = md.digest(str.getBytes());
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < array.length; ++i) {
				sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100)
						.substring(1, 3));
			}
			return sb.toString();
		} catch (java.security.NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
	}

	static String toString(Reader reader) throws IOException {
		StringBuilder sb = new StringBuilder();
		char[] buf = new char[1024];
		int read;
		while ((read = reader.read(buf)) > 0) {
			sb.append(buf, 0, read);
		}
		return sb.toString();
	}

	private static final Pattern CHARSET_PATTERN = Pattern.compile("charset=(\\S+)");

	public static String getCharset(HttpResponse response, String defaultCharset) {
		String charset = defaultCharset;
	    Header[] headers = response.getHeaders("Content-Type");
	    for (Header header : headers) {
	    	Matcher matcher = CHARSET_PATTERN.matcher(header.getValue());
			if (matcher.find()) {
				charset = matcher.group(1);
			}
		}
		return charset;
	}

	public static String extractFirstElement(String html) {
		Matcher matcher = HTML_TAG_PATTERN.matcher(html);
		while (matcher.find() && matcher.group(1) != null); // skip close tags
		LinkedList<String> stack = new LinkedList<String>();
		int start = matcher.start();
		stack.addLast(matcher.group(2));
		while (matcher.find()) {
			String tag = matcher.group(2);
			if (matcher.group().endsWith("/>")) {
				continue;
			}
			if (matcher.group(1) == null) {
				stack.addLast(tag);
			} else {
				while (!stack.getLast().equals(tag) && 
						UNCLOSE_OK_TAGS.contains(stack.getLast())) {
					stack.removeLast();
					if (stack.isEmpty()) {
						return html.substring(start, matcher.start());
					}
				}
				if (!stack.isEmpty() && stack.getLast().equals(tag)) {
					stack.removeLast();
				}
			}
			if (stack.isEmpty()) {
				return html.substring(start, matcher.end());
			}
		}
		return html;
	}

	public static String getInnerHTML(String html) {
		Matcher matcher = ENCLOSING_TAG_PATTERN.matcher(html);
		if (matcher.matches()) {
			return matcher.group(2);
		}
		return html;
	}
	
}
